#pragma once

#include<iostream>
#include<string>
#include<functional>
#include<pthread.h>
#include<unistd.h>
#include<sys/syscall.h>
#include"Logger.hpp"

using func_t = std::function<void(const std::string& name)>;

class Thread
{
public:
    Thread()
    { }
    
    Thread(func_t func, const std::string& name)
        :_func(func)
        ,_name(name)
        ,_is_running(false)
    { 
        LOG(LogLevel::INFO) << "create thread success";
    }

    static void* start_routine(void* args)
    {
        Thread* self = static_cast<Thread*>(args);
        self->_is_running = true;
        self->_lwpid = syscall(SYS_gettid);
        self->_func(self->_name);
        pthread_exit((void*)0);
    }

    void Start()
    {
        int ret = pthread_create(&_tid, nullptr, start_routine, this);
        if(ret == 0)
            LOG(LogLevel::INFO) << _name << " running success";
    }

    void Stop()
    {
        int ret = pthread_cancel(_tid);
        if(ret == 0)
            LOG(LogLevel::INFO) << _name << " stop success";
    }
    
    void Join()
    {
        if(!_is_running)
            return;
        int ret = pthread_join(_tid, nullptr);
        if(ret == 0)
            LOG(LogLevel::INFO) << _name << " join success";
    }

private:
    std::string _name;
    pthread_t _tid;
    func_t _func;
    bool _is_running;
    pid_t _lwpid;
};